
'use strict';

/**
	Part of Zombie Navigator
	Copyright © 2015  Zombie Navigator Developers
	
	@file
	@module
	@license AGPL-3.0+
*/


/* Addon SDK dependencies */
const _toolkitLoader = require('toolkit/loader'); // XXX: Low-level API


/* Used modules */
const _modMeta = require('./meta');


/* Exported APIs */

/**
	@public
*/
const ZOMBIE_API_FUNCTION_NAME = 'getZombieAPI';

/**
	Run a script in a sandbox with provided pseudo-modules
	Note: This needs to use a Low-level API: `toolkit/loader`
	@public
	@method
	@param {string} scriptURI
	@param {object} modulesDesc
	@returns 
*/
const runInSandbox = (scriptURI, modulesDesc) => {
	const {Loader, main} = _toolkitLoader; // XXX: Low-level API
	
	const modMeta = _modMeta;
	
	if ('object' != typeof modulesDesc) {
		modulesDesc = {};
	}
	
	const modules = Object.create(null);
	
	for (let i of Object.getOwnPropertyNames(modulesDesc)) {
		const module = Object.freeze(modulesDesc[i]);
		if ('function' != typeof module[ZOMBIE_API_FUNCTION_NAME]) {
			throw new Error('Invalid Zombie API module: ' + i);
		}
		
		const getAPI = module[ZOMBIE_API_FUNCTION_NAME];
		
		modules[i] = Object.freeze(getAPI('' + scriptURI));
	}
	
	try {
		const loader = Loader({
			paths: {
				"": modMeta.getURIFromDataPath('scripts/modules')
			}
			, modules: modules
			, resolve: function (id, requirer) {
				/*
					Only allow access to special pseudo modules we defined
				*/
				if (id in modules) {
					return id;
				}
				
				
				/*
					Block access to any real module
				*/
				throw new Error('No such module: ' + id);
			}
			, globals: {
				//dump: null
			}
		});
		
		return main(loader, scriptURI);
	} catch (e) {
		throw new Error(e + '');
	}
	
};


/* Exports */
exports.ZOMBIE_API_FUNCTION_NAME = ZOMBIE_API_FUNCTION_NAME;
exports.runInSandbox = runInSandbox;


// vim: ts=4 noet ai

